﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using ICeFramework.Common.DataLayer.Interfaces;
using System.Runtime.Serialization;
using System.ServiceModel;
using ICeFramework.Common.DataLayer.Enums;

namespace ICeFramework.Common.DataLayer
{
    [Serializable, DataContract]
    public class EntityColumn : IEntityColumn
    {
        private ValidationFlags _validation;
        #region public ValidationFlags Validation
        /// <summary>
        /// Get/Sets the Validation of the EntityColumn
        /// </summary>
        /// <value></value>
        [DataMember]
        public ValidationFlags Validation
        {
            get { return _validation; }
            set { _validation = value; }
        }
        #endregion

        [DataMember]
        private DbType _dbType;
        #region public DbType DbType
        /// <summary>
        /// Gets the DbType of the EntityColumn
        /// </summary>
        /// <value></value>        
        public DbType DbType
        {
            get { return _dbType; }
        }
        #endregion

        private Type _columnType;
        #region public Type ColumnType
        /// <summary>
        /// Get/Sets the ColumnType of the EntityColumn
        /// </summary>
        /// <value></value>
        public Type ColumnType
        {
            get
            {
                if (_columnType == null)
                {
                    SetColumnType(_dbType);
                }
                return _columnType;

            }
            set { _columnType = value; }
        }
        #endregion

        [DataMember]
        private string _name;
        #region public string Name
        /// <summary>
        /// Gets the Name of the EntityColumn
        /// </summary>
        /// <value></value>
        public string Name
        {
            get { return _name; }
        }
        #endregion

        [DataMember]
        private string _displayName;
        #region public string DisplayName
        /// <summary>
        /// Get/Sets the DisplayName of the EntityColumn
        /// </summary>
        /// <value></value>
        public string DisplayName
        {
            get { return _displayName; }
            set { _displayName = value; }
        }
        #endregion

        [DataMember]
        private bool _isInPrimaryKeys;
        #region public bool IsInPrimaryKeys
        /// <summary>
        /// Gets the IsInPrimaryKeys of the EntityColumn
        /// </summary>
        /// <value></value>
        public bool IsInPrimaryKeys
        {
            get { return _isInPrimaryKeys; }
        }
        #endregion

        [DataMember]
        private bool _isForeignKey;
        #region public bool IsForeignKey
        /// <summary>
        /// Gets the IsForeignKey of the EntityColumn
        /// </summary>
        /// <value></value>
        public bool IsForeignKey
        {
            get { return _isForeignKey; }
        }
        #endregion

        [DataMember]
        private int? _length;
        #region public int? Length
        /// <summary>
        /// Gets the Length of the EntityColumn
        /// </summary>
        /// <value></value>
        public int? Length
        {
            get { return _length; }
        }
        #endregion

        [DataMember]
        private int? _precision;
        #region public int? Precision
        /// <summary>
        /// Gets the Precision of the EntityColumn
        /// </summary>
        /// <value></value>
        public int? Precision
        {
            get { return _precision; }
        }
        #endregion

        [DataMember]
        private int? _scale;
        #region public int? Scale
        /// <summary>
        /// Gets the Scale of the EntityColumn
        /// </summary>
        /// <value></value>
        public int? Scale
        {
            get { return _scale; }
        }
        #endregion

        [DataMember]
        private bool _allowNull;
        #region public bool AllowNull
        /// <summary>
        /// Gets the AllowNull of the EntityColumn
        /// </summary>
        /// <value></value>
        public bool AllowNull
        {
            get { return _allowNull; }
        }
        #endregion

        [DataMember]
        private object _defaultValue;
        #region public object DefaultValue
        /// <summary>
        /// Get/Sets the DefaultValue of the EntityColumn
        /// </summary>
        /// <value></value>
        public object DefaultValue
        {
            get { return _defaultValue; }
            set { _defaultValue = value; }
        }
        #endregion

        [DataMember]
        private bool _isReadOnly;
        #region public bool IsReadOnly
        /// <summary>
        /// Gets the IsReadOnly of the EntityColumn
        /// </summary>
        /// <value></value>
        public bool IsReadOnly
        {
            get { return _isReadOnly; }
        }
        #endregion

        #region public EntityColumn(string name, DbType dbType, bool isInPrimaryKeys, bool isForeignKey, bool allowNull, int? length, int? precision, int? scale, object defaultValue, bool isReadOnly)
        /// <summary>
        /// Initializes a new instance of the <b>EntityColumn</b> class.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="dbType"></param>
        /// <param name="isInPrimaryKeys"></param>
        /// <param name="isForeignKey"></param>
        /// <param name="allowNull"></param>
        /// <param name="length"></param>
        /// <param name="precision"></param>
        /// <param name="scale"></param>
        /// <param name="defaultValue"></param>
        /// <param name="isReadOnly"></param>
        public EntityColumn(string name, DbType dbType, bool isInPrimaryKeys, bool isForeignKey, bool allowNull, int? length, int? precision, int? scale, object defaultValue, bool isReadOnly)
        {
            _name = name;
            _dbType = dbType;
            _displayName = name;
            _isInPrimaryKeys = isInPrimaryKeys;
            _isForeignKey = isForeignKey;
            _allowNull = allowNull;
            _length = length;
            _precision = precision;
            _scale = scale;
            _defaultValue = defaultValue;
            _isReadOnly = isReadOnly;
            SetColumnType(_dbType);
        }
        #endregion

        #region private void SetColumnType(DbType dbType)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbType"></param>
        private void SetColumnType(DbType dbType)
        {
            switch (dbType)
            {
                case DbType.AnsiString:
                case DbType.AnsiStringFixedLength:
                case DbType.StringFixedLength:
                case DbType.String:
                    _columnType = typeof(string);
                    break;
                case DbType.Binary:
                    _columnType = typeof(byte[]);
                    break;
                case DbType.Boolean:
                    _columnType = typeof(bool);
                    break;
                case DbType.Byte:
                    _columnType = typeof(byte);
                    break;
                case DbType.Currency:
                    _columnType = typeof(decimal);
                    break;
                case DbType.Date:
                case DbType.DateTime:
                case DbType.DateTime2:
                case DbType.Time:
                    _columnType = typeof(DateTime);
                    break;
                case DbType.DateTimeOffset:
                    _columnType = typeof(TimeSpan);
                    break;
                case DbType.Decimal:
                    _columnType = typeof(decimal);
                    break;
                case DbType.Double:
                    _columnType = typeof(double);
                    break;
                case DbType.Guid:
                    _columnType = typeof(Guid);
                    break;
                case DbType.Int16:
                    _columnType = typeof(Int16);
                    break;
                case DbType.Int32:
                    _columnType = typeof(Int32);
                    break;
                case DbType.Int64:
                    _columnType = typeof(Int64);
                    break;
                case DbType.Object:
                    _columnType = typeof(object);
                    break;
                case DbType.Single:
                    _columnType = typeof(Single);
                    break;
                case DbType.UInt16:
                    _columnType = typeof(UInt16);
                    break;
                case DbType.UInt32:
                    _columnType = typeof(UInt32);
                    break;
                case DbType.UInt64:
                    _columnType = typeof(UInt64);
                    break;
                case DbType.VarNumeric:
                    _columnType = typeof(object);
                    break;
                case DbType.Xml:
                    _columnType = typeof(string);
                    break;
                default:
                    _columnType = typeof(object);
                    break;
            }
        }
        #endregion

        #region public static EntityFilter operator >=(EntityColumn a, object b)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static EntityFilter operator >=(EntityColumn a, object b)
        {
            EntityFilter q = new EntityFilter();
            q.Column = a;
            q.Expression = b;
            q.Operator = ">=";
            return q;
        }
        #endregion

        #region public static EntityFilter operator <=(EntityColumn a, object b)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static EntityFilter operator <=(EntityColumn a, object b)
        {
            EntityFilter q = new EntityFilter();
            q.Column = a;
            q.Expression = b;
            q.Operator = "<=";
            return q;
        }
        #endregion

        #region public static EntityFilter operator ==(EntityColumn a, object b)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static EntityFilter operator ==(EntityColumn a, object b)
        {
            EntityFilter q = new EntityFilter();
            q.Column = a;
            if (b == null)
            {
                q.Operator = " IS ";
                q.Expression = null;
            }
            else
            {
                q.Operator = "=";
                q.Expression = b;
            }
            return q;
        }
        #endregion

        #region public static EntityFilter operator !=(EntityColumn a, object b)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static EntityFilter operator !=(EntityColumn a, object b)
        {
            EntityFilter q = new EntityFilter();
            q.Column = a;
            if (b == null)
            {
                q.Operator = " IS NOT ";
                q.Expression = null;
            }
            else
            {
                q.Operator = "<>";
                q.Expression = b;
            }
            return q;
        }
        #endregion

        #region public static EntityFilter operator <(EntityColumn a, object b)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static EntityFilter operator <(EntityColumn a, object b)
        {
            EntityFilter q = new EntityFilter();
            q.Column = a;
            q.Expression = b;
            q.Operator = "<";
            return q;
        }
        #endregion

        #region public static EntityFilter operator >(EntityColumn a, object b)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static EntityFilter operator >(EntityColumn a, object b)
        {
            EntityFilter q = new EntityFilter();
            q.Column = a;
            q.Expression = b;
            q.Operator = ">";
            return q;
        }
        #endregion

        #region public EntityFilter Like(object b)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="b"></param>
        /// <returns></returns>
        public EntityFilter Like(object b)
        {
            EntityFilter q = new EntityFilter();
            q.Column = this;
            q.Expression = b;
            q.Operator = " LIKE ";
            return q;
        }
        #endregion

        private EntityOrder _asc;
        public EntityOrder Asc
        {
            get
            {
                if (_asc == null)
                {
                    _asc = new EntityOrder(this, EntityOrderDirection.Asc);
                }
                return _asc;
            }
        }

        private EntityOrder _desc;
        public EntityOrder Desc
        {
            get
            {
                if (_desc == null)
                {
                    _desc = new EntityOrder(this, EntityOrderDirection.Desc);
                }
                return _desc;
            }
        }
    }
}
